package com.sparrow.common.cd;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 通用的cd控制器
 * @param <K>
 */
public class CDBox<K> {
    /**
     * key是任意类型 value为毫秒到期时间
     */
    private final ConcurrentHashMap<K, Long> times = new ConcurrentHashMap<>();

    /**
     * 判断是否正在冷却中（并进行惰性清理）
     * @param key CD 键
     * @return true 表示冷却中，false 表示可用或不存在
     */
    public boolean isCoding(K key, long duration) {
        cleanup();
        Long endTime = times.get(key);
        if (endTime == null) {
            long newEndTime = System.currentTimeMillis() + duration;
            endTime = times.putIfAbsent(key, newEndTime);
            if (endTime == null) {
                return false; // 刚刚设置进去，不在冷却中
            }
        }
        return System.currentTimeMillis() < endTime;
    }


    /**
     * 获取剩余CD时间（并进行惰性清理）
     * @param key CD 键
     * @return 剩余时间（毫秒），为0表示无CD或已结束
     */
    public long getRemaining(K key) {
        cleanup();
        Long endTime = times.get(key);
        if (endTime == null) return 0;
        return Math.max(0, endTime - System.currentTimeMillis());
    }

    /**
     * 清除某个CD
     */
    public void clearCD(K key) {
        times.remove(key);
    }

    /**
     * 清除所有CD
     */
    public void clearAll() {
        times.clear();
    }

    /**
     * 惰性清理：移除所有过期CD
     */
    private void cleanup() {
        long now = System.currentTimeMillis();
        for (Map.Entry<K, Long> entry : times.entrySet()) {
            if (entry.getValue() < now) {
                times.remove(entry.getKey(), entry.getValue()); // 并发安全地移除
            }
        }
    }

    public long getEndTime(K key) {
        cleanup();
        Long endTime = times.get(key);
        if (endTime == null) return 0;
        return endTime;
    }
}
